import aiohttp
import json
import asyncio
import logging
from typing import Dict, Any, Optional, List

from .ai_base import BaseAIService, GenerationRequest, GenerationResponse, AIServiceProvider, AIServiceType
from app.core.error_handler import robust_executor, with_retry
from .jimeng_image_fusion_service import JimengImageFusionService
from app.utils.jimeng_signature_helper import JimengSignatureHelper

logger = logging.getLogger(__name__)

class JimengAIService(BaseAIService):
    """即梦AI服务实现 - 基于火山引擎API"""
    
    def __init__(self, config: Dict[str, Any]):
        super().__init__(config)
        self.access_key = config.get("api_key")  # 实际是AccessKey
        self.secret_key = config.get("user_id")  # 实际是SecretKey
        
        # 火山引擎API配置
        self.host = "visual.volcengineapi.com"
        self.endpoint = "https://visual.volcengineapi.com"
        self.region = "cn-north-1"
        self.service = "cv"
        # 视频生成接口映射
        self.video_req_keys = {
            "720p": "jimeng_i2v_first_v30",      # 720p高清接口
            "1080p": "jimeng_i2v_first_v30_1080" # 1080p超清接口
        }
        self.image_fusion_req_key = "jimeng_i2i_v30"      # 以图生图
        self.text_to_image_req_key = "jimeng_t2i_v31"     # 文本生图
        
        # 即梦AI特殊配置
        self.max_duration = config.get("max_duration", 10)  # 支持5s、10s
        self.default_aspect_ratio = config.get("default_aspect_ratio", "16:9")
        
        # 初始化签名工具和图片融合服务
        self.signature_helper = JimengSignatureHelper(
            self.access_key, self.secret_key, self.host, self.region, self.service
        )
        self.image_fusion_service = JimengImageFusionService(self)
    
    def get_provider_name(self) -> AIServiceProvider:
        return AIServiceProvider.JIMENG_AI
    
    def get_supported_services(self) -> List[AIServiceType]:
        return [
            AIServiceType.VIDEO_GENERATION,
            AIServiceType.IMAGE_GENERATION,  # 新增图片融合支持
        ]
    # === 图片融合方法委托 ===
    async def generate_image_fusion(self, request: GenerationRequest) -> GenerationResponse:
        """图片融合生成 - 委托给独立的融合服务"""
        return await self.image_fusion_service.generate_image_fusion(request)

    async def generate_video(self, request: GenerationRequest) -> GenerationResponse:
        """生成视频内容 - 带错误处理和重试"""
        return await robust_executor.execute_with_retry(
            self._generate_video_internal,
            "jimeng_ai",
            request
        )
    
    async def _generate_video_internal(self, request: GenerationRequest) -> GenerationResponse:
        """内部视频生成方法"""
        try:
            # 构建请求参数
            payload = self._build_video_generation_payload(request)
            query_params = {
                'Action': 'CVSync2AsyncSubmitTask',
                'Version': '2022-08-31'
            }
            
            # 生成签名头
            body_json = json.dumps(payload)
            headers = self.signature_helper.generate_v4_signature('POST', query_params, body_json)
            
            # 构建URL
            query_string = self.signature_helper._format_query(query_params)
            url = f"{self.endpoint}?{query_string}"
            
            # 详细日志：记录请求信息
            logger.info(f"📤 即梦AI 720p接口请求")
            logger.info(f"   URL: {url}")
            logger.info(f"   Payload: {json.dumps(payload, ensure_ascii=False)}")
            logger.info(f"   Headers: {headers}")
            
            # 发送请求
            async with aiohttp.ClientSession() as session:
                async with session.post(
                    url,
                    headers=headers,
                    data=body_json,
                    timeout=aiohttp.ClientTimeout(total=300)
                ) as response:
                    
                    # 详细日志：记录响应信息
                    logger.info(f"📥 即梦AI响应状态: {response.status}")
                    response_text = await response.text()
                    logger.info(f"📥 即梦AI响应内容: {response_text}")
                    
                    if response.status == 200:
                        try:
                            result = await response.json()
                            logger.info(f"✅ 即梦AI响应解析成功: {json.dumps(result, ensure_ascii=False)}")
                            return await self._process_video_generation_response(result, request)
                        except json.JSONDecodeError as e:
                            logger.error(f"❌ 即梦AI响应JSON解析失败: {e}")
                            logger.error(f"   原始响应: {response_text}")
                            raise Exception(f"即梦AI响应格式错误: {e}")
                    else:
                        logger.error(f"❌ 即梦AI API错误 ({response.status}): {response_text}")
                        return self._handle_api_error(response.status, response_text)
                        
        except asyncio.TimeoutError:
            raise Exception("Request timeout - 即梦AI generation took too long")
        except aiohttp.ClientError as e:
            raise Exception(f"Network error - connection failed: {str(e)}")
        except Exception as e:
            raise e
    
    def _build_video_generation_payload(self, request: GenerationRequest) -> Dict[str, Any]:
        """构建视频生成请求payload"""
        
        # 获取分辨率参数，默认720p
        resolution = request.params.get("resolution", "720p")
        if resolution not in self.video_req_keys:
            resolution = "720p"  # fallback to 720p
        
        # 基础参数
        payload = {
            "req_key": self.video_req_keys[resolution],
            "prompt": request.prompt,
        }
        
        # 时长参数 (转换为帧数)
        duration = min(request.params.get("duration", 5), self.max_duration)
        if duration <= 5:
            payload["frames"] = 121  # 5秒
        else:
            payload["frames"] = 241  # 10秒
        
        # 宽高比参数 - 直接使用传入的aspect_ratio
        aspect_ratio = request.params.get("aspect_ratio", "16:9")
        payload["aspect_ratio"] = aspect_ratio
        
        # 种子参数
        seed = request.params.get("seed")
        if isinstance(seed, int) and seed >= 0:
            payload["seed"] = seed
        else:
            payload["seed"] = -1
        
        # 图片转视频参数处理
        source_image_url = request.params.get("source_image_url")
        source_image_base64 = request.params.get("source_image_base64")
        
        if source_image_url:
            # 使用图片URL
            payload["image_urls"] = [source_image_url]  # API需要一个列表
            image_strength = request.params.get("image_strength", 0.8)
            payload["strength"] = image_strength
        elif source_image_base64:
            # 使用base64图片数据
            payload["binary_data_base64"] = [source_image_base64] # API需要一个列表
            image_strength = request.params.get("image_strength", 0.8)
            payload["strength"] = image_strength
        
        return payload
    
    def _convert_resolution_to_aspect_ratio(self, resolution: str) -> str:
        """转换分辨率到宽高比"""
        resolution_mapping = {
            "640x480": "4:3",
            "1280x720": "16:9", 
            "1920x1080": "16:9",
            "512x512": "1:1",
            "768x768": "1:1",
            "1080x1920": "9:16",
            "720x1280": "9:16"
        }
        return resolution_mapping.get(resolution, "16:9")
    
    def _handle_api_error(self, status_code: int, error_text: str) -> GenerationResponse:
        """处理API错误"""
        error_message = f"即梦AI API错误 ({status_code}): {error_text}"
        
        # 详细记录错误信息
        logger.error(f"🚨 即梦AI API错误详情:")
        logger.error(f"   状态码: {status_code}")
        logger.error(f"   错误内容: {error_text}")
        
        if status_code == 400:
            # 解析具体错误
            try:
                error_data = json.loads(error_text)
                code = error_data.get("code", 0)
                message = error_data.get("message", "参数错误")
                
                logger.error(f"   错误代码: {code}")
                logger.error(f"   错误消息: {message}")
                
                if code == 50411:
                    error_message = "输入图片前审核未通过"
                elif code == 50412:
                    error_message = "输入文本前审核未通过"
                elif code == 50413:
                    error_message = "输入文本含敏感词、版权词等审核不通过"
                else:
                    error_message = f"请求参数错误: {message}"
            except:
                error_message = f"请求参数错误: {error_text}"
                
        elif status_code == 429:
            error_message = "请求频率超限，请稍后重试"
        elif status_code >= 500:
            error_message = "服务器内部错误，请稍后重试"
        
        return GenerationResponse(
            success=False,
            error_message=error_message
        )
    
    async def _process_video_generation_response(self, result: Dict[str, Any], request: GenerationRequest) -> GenerationResponse:
        """处理视频生成响应"""
        try:
            # 检查响应状态
            code = result.get("code", 0)
            if code != 10000:
                message = result.get("message", "请求失败")
                return GenerationResponse(
                    success=False,
                    error_message=f"即梦AI错误: {message} (code: {code})"
                )
            
            # 获取任务ID
            data = result.get("data", {})
            task_id = data.get("task_id")
            
            if not task_id:
                return GenerationResponse(
                    success=False,
                    error_message="即梦AI未返回任务ID"
                )
            
            # 获取当前请求使用的分辨率和对应的req_key
            resolution = request.params.get("resolution", "720p")
            if resolution not in self.video_req_keys:
                resolution = "720p"
            req_key = self.video_req_keys[resolution]
            
            # 异步任务，需要轮询获取结果
            video_url = await self._wait_for_task_completion(task_id, req_key)
            
            if not video_url:
                return GenerationResponse(
                    success=False,
                    error_message="视频生成失败或超时"
                )
            
            return self._build_success_response(video_url, task_id, request)
            
        except Exception as e:
            return GenerationResponse(
                success=False,
                error_message=f"处理即梦AI响应失败: {str(e)}"
            )
    
    async def _poll_task_result(self, task_id: str, req_key: str, max_wait_time: int = 300) -> Optional[Dict[str, Any]]:
        """通用任务结果轮询方法"""
        wait_time = 0
        check_interval = 10  # 每10秒检查一次
        
        while wait_time < max_wait_time:
            try:
                task_detail = await self._get_task_detail(task_id, req_key)
                
                if task_detail:
                    status = task_detail.get("status")
                    if status == "done":
                        return task_detail
                    elif status in ["not_found", "expired"]:
                        return None
                
                # 等待下一次检查
                await asyncio.sleep(check_interval)
                wait_time += check_interval
                
            except Exception:
                # 如果状态查询失败，继续等待
                await asyncio.sleep(check_interval)
                wait_time += check_interval
        
        return None

    async def _wait_for_task_completion(self, task_id: str, req_key: str = None, max_wait_time: int = 300) -> Optional[str]:
        """等待视频任务完成并获取结果"""
        # 如果没有指定req_key，默认使用720p
        if not req_key:
            req_key = self.video_req_keys["720p"]
        result = await self._poll_task_result(task_id, req_key, max_wait_time)
        if result and result.get("status") == "done":
            return result.get("video_url")
        return None
    
    async def _get_task_detail(self, task_id: str, req_key: str = None) -> Optional[Dict[str, Any]]:
        """获取任务详情"""
        try:
            # 构建查询请求
            req_json_payload = {"return_url": True}
            payload = {
                "req_key": req_key or self.video_req_keys["720p"],  # 使用传入的req_key，默认为720p
                "task_id": task_id,
                "req_json": json.dumps(req_json_payload)
            }
            
            query_params = {
                'Action': 'CVSync2AsyncGetResult',
                'Version': '2022-08-31'
            }
            
            # 生成签名
            body_json = json.dumps(payload)
            headers = self.signature_helper.generate_v4_signature('POST', query_params, body_json)
            
            # 构建URL
            query_string = self.signature_helper._format_query(query_params)
            url = f"{self.endpoint}?{query_string}"
            
            async with aiohttp.ClientSession() as session:
                async with session.post(
                    url,
                    headers=headers,
                    data=body_json,
                    timeout=aiohttp.ClientTimeout(total=30)
                ) as response:
                    
                    if response.status == 200:
                        result = await response.json()
                        if result.get("code") == 10000:
                            return result.get("data", {})
                    
        except Exception:
            pass
        
        return None
    
    def _build_success_response(self, video_url: str, task_id: str, request: GenerationRequest) -> GenerationResponse:
        """构建成功响应"""
        return GenerationResponse(
            success=True,
            result_url=video_url,
            metadata={
                "task_id": task_id,
                "duration": request.params.get("duration", 5),
                "provider": "jimeng_ai",
                "aspect_ratio": self._convert_resolution_to_aspect_ratio(
                    request.params.get("resolution", "16:9")
                ),
                "frames": 241 if request.params.get("duration", 5) > 5 else 121,
                "seed": request.params.get("seed", -1)
            },
            cost=self.calculate_cost(request)
        )
    
    async def generate_image(self, request: GenerationRequest) -> GenerationResponse:
        """
        即梦AI图片生成
        支持文本生图和以图生图两种模式
        """
        try:
            generation_type = request.params.get("generation_type", "text_to_image")
            
            if generation_type == "image_to_image":
                # 以图生图模式 - 使用已有的图片融合功能
                logger.info("调用即梦AI以图生图接口")
                return await self.generate_image_fusion(request)
            elif generation_type == "text_to_image":
                # 文本生图模式
                logger.info("调用即梦AI文本生图接口")
                return await self._generate_text_to_image(request)
            else:
                return GenerationResponse(
                    success=False,
                    error_message=f"不支持的生成类型: {generation_type}"
                )
                
        except Exception as e:
            logger.error(f"即梦AI图片生成失败: {str(e)}")
            return GenerationResponse(
                success=False,
                error_message=f"图片生成失败: {str(e)}"
            )
    
    async def _generate_text_to_image(self, request: GenerationRequest) -> GenerationResponse:
        """
        即梦AI文本生图实现
        """
        try:
            # 构建文本生图请求参数
            aspect_ratio = request.params.get("aspect_ratio", "1:1")
            width, height = self._get_dimensions_by_aspect_ratio(aspect_ratio)
            
            payload = {
                "req_key": self.text_to_image_req_key,
                "prompt": request.prompt,
                "seed": request.params.get("seed", -1),
                "width": width,
                "height": height
            }
            
            logger.info(f"即梦AI文本生图请求: {payload}")
            
            # 提交任务
            submit_response = await self._submit_async_task(payload)
            if not submit_response.success:
                return submit_response
            
            task_id = submit_response.task_id
            logger.info(f"即梦AI文本生图任务提交成功: {task_id}")
            
            # 轮询获取结果
            result = await self._poll_task_result(task_id, self.text_to_image_req_key)
            
            if result.success:
                logger.info(f"即梦AI文本生图完成: {result.image_url}")
                return GenerationResponse(
                    success=True,
                    image_url=result.image_url,
                    cost=0.1,  # 默认成本
                    metadata={
                        "task_id": task_id,
                        "service": "jimeng_ai",
                        "generation_type": "text_to_image",
                        "aspect_ratio": aspect_ratio,
                        "dimensions": f"{width}x{height}"
                    }
                )
            else:
                return GenerationResponse(
                    success=False,
                    error_message=result.error or "文本生图失败"
                )
                
        except Exception as e:
            logger.error(f"即梦AI文本生图异常: {str(e)}")
            return GenerationResponse(
                success=False,
                error_message=f"文本生图异常: {str(e)}"
            )
    
    def _get_dimensions_by_aspect_ratio(self, aspect_ratio: str) -> tuple[int, int]:
        """根据宽高比获取对应的宽高尺寸"""
        aspect_ratio_mapping = {
            "1:1": (1328, 1328),    # 1:1
            "4:3": (1472, 1104),    # 4:3
            "3:2": (1584, 1056),    # 3:2
            "16:9": (1664, 936),    # 16:9
            "21:9": (2016, 864),    # 21:9
        }
        return aspect_ratio_mapping.get(aspect_ratio, (1664, 936))  # 默认16:9
    
    async def edit_image(self, request: GenerationRequest, image_url: str) -> GenerationResponse:
        """图片编辑不支持"""
        return GenerationResponse(
            success=False,
            error_message="即梦AI不支持图片编辑功能"
        )
    
    async def face_swap(self, request: GenerationRequest, source_url: str, target_url: str) -> GenerationResponse:
        """人脸替换不支持"""
        return GenerationResponse(
            success=False,
            error_message="即梦AI不支持人脸替换功能"
        )
    
    async def get_task_status(self, task_id: str) -> str:
        """获取任务状态"""
        return await robust_executor.execute_with_retry(
            self._get_task_status_internal,
            "jimeng_ai_status",
            task_id
        )
    
    async def _get_task_status_internal(self, task_id: str) -> str:
        """内部任务状态查询方法"""
        try:
            task_detail = await self._get_task_detail(task_id)
            
            if not task_detail:
                return "not_found"
            
            status = task_detail.get("status", "unknown")
            
            # 映射即梦AI状态到标准状态
            status_mapping = {
                "in_queue": "processing",
                "generating": "processing", 
                "done": "completed",
                "not_found": "not_found",
                "expired": "failed"
            }
            
            return status_mapping.get(status, "processing")
        
        except Exception:
            return "processing"
    
    def validate_config(self) -> bool:
        """验证配置是否正确"""
        try:
            if not self.access_key or not self.secret_key:
                return False
            
            if self.max_duration <= 0 or self.max_duration > 10:
                return False
            
            return True
        except Exception:
            return False
    
    def calculate_cost(self, request: GenerationRequest) -> float:
        """估算成本"""
        try:
            # 即梦AI 3.0 Pro定价估算
            duration = request.params.get("duration", 5)
            
            if not isinstance(duration, (int, float)) or duration <= 0:
                duration = 5
            
            # 基础成本 - 即梦AI 3.0 Pro相对较高
            if duration <= 5:
                base_cost = 0.15  # 5秒基础成本
            else:
                base_cost = 0.25  # 10秒基础成本
            
            # 宽高比成本倍数
            aspect_ratio = self._convert_resolution_to_aspect_ratio(
                request.params.get("resolution", "16:9")
            )
            aspect_multiplier = {
                "1:1": 1.0,
                "4:3": 1.1,
                "16:9": 1.2,
                "3:4": 1.1,
                "9:16": 1.2,
                "21:9": 1.3
            }.get(aspect_ratio, 1.2)
            
            # 图片转视频成本更高
            mode_multiplier = 1.5 if request.params.get("source_image_url") else 1.0
            
            total_cost = base_cost * aspect_multiplier * mode_multiplier
            
            return round(total_cost, 3)
            
        except Exception:
            # 默认估算成本
            return 0.15